﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Emgu.CV;
using Emgu.CV.Structure;

namespace AsmDotNet
{
    public class FlandMark
    {
        private List<List<int>> _lines = new List<List<int>>
            {
                new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
                new List<int> {48,49,50,51,52,53,54,55,56,57,58,59,48},
                new List<int> {37,38,39,40,41,42,43,44,45},
                 new List<int> {27,28,29,30,27},
                 new List<int> {32,33,34,35,32},
                 new List<int> {21,22,23,24},
                  new List<int> {15,16,17,18},
            };
        private double Sin, Cos, Norm;
        public FlandMark()
        {
            Points = new List<PointF>();
        }

        /// <summary>
        /// </summary>
        /// <param name="points">Points and angle from asmlibrarydotnet</param>
        public FlandMark(string points)
        {
            Points = new List<PointF>();
            string[] lines = points.Split('\r');
            foreach (string s in lines)
            {

                string[] p = s.Split(' ');
                if (p.Length == 2)
                    Points.Add(new PointF((float)Convert.ToDouble(p[0].Replace('.', ',')), (float)Convert.ToDouble(p[1].Replace('.', ','))));
                if (p.Length == 3)
                {
                    Sin = Convert.ToDouble(p[1].Replace('.', ','));
                    Cos = Convert.ToDouble(p[2].Replace('.', ','));
                    Norm = Convert.ToDouble(p[0].Replace('.', ','));
                }
            }
            
        }

        /// <summary>
        /// Angle vertical(radian)
        /// </summary>
        public double Angle { get { return Math.Asin(Sin); } }

        /// <summary>
        /// Points
        /// </summary>
        public List<PointF> Points { get; set; }

        /// <summary>
        /// Draw lines on input images
        /// </summary>
        public void DrawLines(Image<Bgr,byte> image, int dx=0, int dy=0)
        {
            foreach (var line in _lines)
                for (int i = 0; i < line.Count - 1; i++)
                    image.Draw(new LineSegment2DF(new Point(Convert.ToInt32(Points[line[i]].X + dx), Convert.ToInt32(Points[line[i]].Y + dy)), new Point(Convert.ToInt32(Points[line[i + 1]].X + dx), Convert.ToInt32(Points[line[i+1]].Y + dy))), new Bgr(255, 0, 0), 2);
        }

        /// <summary>
        /// Draw lines on input images
        /// </summary>
        public void DrawText(Image<Bgr, byte> image,int dx=0,int dy=0)
        {
                                MCvFont font = new MCvFont( Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 0.5,0.5);
            for (int i = 0; i < Points.Count; i++)
                image.Draw(i.ToString(), ref font,
                           new Point(Convert.ToInt32(Points[i].X + dx), Convert.ToInt32(Points[i].Y + dy)),
                           new Bgr(255, 0, 0));
        }

        /// <summary>
        /// Draw lines, return NEW bitmap!!!
        /// </summary>
        public Bitmap DrawLines(Bitmap image,int dx=0, int dy=0)
        {
            var im = new Image<Bgr, byte>(image);
            DrawLines(im,dx,dy);
            var r = im.ToBitmap();
            im.Dispose();
            return r;
        }

        /// <summary>
        /// Draw lines, return NEW bitmap!!!
        /// </summary>
        public Bitmap DrawText(Bitmap image, int dx = 0, int dy = 0)
        {
            var im = new Image<Bgr, byte>(image);
            DrawText(im,dx,dy);
            var r = im.ToBitmap();
            im.Dispose();
            return r;
        }

    }
}
